﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Golem.Indexer.Data;
using System.IO;
using System.Management;
using Trinet.Networking;
using System.Threading;
using System.Threading.Tasks;

namespace Golem.Indexer.Indexers
{
    internal class SambaIndexer : Indexer
    {
        public SambaIndexer()
            : base(Protocol.Samba)
        {
        }

        private String[] GetShares(String ip)
        {
            List<String> shareDirectories = new List<string>();

            var shi = ShareCollection.GetShares(ip);
            
            if (shi != null)
            {
                foreach (Share si in shi)
                {
                    if (si.IsFileSystem)
                    {
                        if (!this.IndexHidden && (si.Root.Name.EndsWith("$") || si.ShareType == ShareType.Special))
                            continue;

                        shareDirectories.Add(si.Root.Name);
                    }
                }
            }

            return shareDirectories.ToArray();
        }

        private List<FileDescriptor> GetFileDescriptors(String[] files)
        {
            var descriptors = new List<FileDescriptor>();

            foreach (var file in files)
            {
                FileInfo info = new FileInfo(file);
                var ext = info.Extension;

                if (ext.Length > 0)
                    ext = info.Extension.Substring(1);

                var descriptor = new FileDescriptor(info.Name, info.FullName, info.Length, FileDescriptor.GetTypeOfFile(ext));
                descriptors.Add(descriptor);
            }

            return descriptors;
        }

        private void GetPaths(String path, MachineDescriptor machine)
        {
            try
            {
                var directories = Directory.GetDirectories(path);
                var files = Directory.GetFiles(path);
                var fileDescriptors = GetFileDescriptors(files);

                this.IndexFiles(machine, fileDescriptors);

                foreach (var dir in directories)
                    GetPaths(dir, machine);
            }
            catch (UnauthorizedAccessException ex)
            {
                //we don't have permission, so we skip these files
                this.ThrowException(ex);
            }
            catch (IOException ex)
            {
                //some file or directory isn't available
                this.ThrowException(ex);
            }
        }

        protected override void GetFiles(MachineDescriptor machine)
        {
            var shares = this.GetShares(machine.IP);

            foreach (var share in shares)
            {
                var directory = String.Format(@"\\{0}\{1}", machine.IP, share);
                GetPaths(directory, machine);
            }
        }
    }
}
